/**
 * @file    gt98xx_drv_gpio.h
 * @author  Giantec-Semi ATE
 * @brief   Header file of TIMER driver module.
 * @version 0.1
 * 
 * @copyright Copyright (c) 2021 Giantec-Semi
 * 
 */

#ifndef GT98XX_DRIVERS_GT98XX_DRV_GPIO_H_
#define GT98XX_DRIVERS_GT98XX_DRV_GPIO_H_

#ifdef __cplusplus
  extern "C" {
#endif /* __cplusplus */

#include "gt98xx_drv_def.h"
#include "gt98xx_drv_conf.h"

/**
 * @addtogroup GT9881_Drivers
 * @{
 */

/**
 * @defgroup GPIO_DRV GPIO Drivers
 * @{
 */

/**
 * @defgroup GPIO_DRV_Exported_Types GPIO Drivers Exported Types
 * @{
 */

/**
 * @struct DrvGpioInitTypedef
 * @brief  GPIO drivers init structure definition
 */
typedef struct tagDrvGpioInitTypedef {
  uint32_t data;                  ///< GPIO data
  uint32_t pin;                  ///< GPIO pin
  uint32_t function;             ///< GPIO function
  uint32_t dir;                  ///< GPIO input/output
  uint32_t out_mode;             ///< GPIO out mode
  uint32_t speed;                ///< GPIO speed
  uint32_t pull_up_down;         ///< GPIO pull up/down
} DrvGpioInitTypedef;
/** @} GPIO_DRV_Exported_Types */
 
/**
 * @defgroup GPIO_DRV_Exported_Constants GPIO Drivers Exported Constants
 * @{
 */

/**
 * @defgroup GPIO_DRV_EC_PIN GPIO pin
 * @{
 */
#define DRV_GPIO_PIN_0                     0         ///< GPIO pin 0
#define DRV_GPIO_PIN_1                     1         ///< GPIO pin 1
#define DRV_GPIO_PIN_2                     2         ///< GPIO pin 2
#define DRV_GPIO_PIN_3                     3         ///< GPIO pin 3
#define DRV_GPIO_PIN_4                     4         ///< GPIO pin 4
#define DRV_GPIO_PIN_5                     5         ///< GPIO pin 5
#define DRV_GPIO_PIN_6                     6         ///< GPIO pin 6
#define DRV_GPIO_PIN_7                     7         ///< GPIO pin 7
#define DRV_GPIO_PIN_8                     8         ///< GPIO pin 8
#define DRV_GPIO_PIN_9                     9         ///< GPIO pin 9
#define DRV_GPIO_PIN_10                    10        ///< GPIO pin 10
#define DRV_GPIO_PIN_11                    11        ///< GPIO pin 11
#define DRV_GPIO_PIN_12                    12        ///< GPIO pin 12
#define DRV_GPIO_PIN_13                    13        ///< GPIO pin 13
#define DRV_GPIO_PIN_14                    14        ///< GPIO pin 14
#define DRV_GPIO_PIN_15                    15        ///< GPIO pin 15
#define DRV_GPIO_PIN_16                    16        ///< GPIO pin 16
#define DRV_GPIO_PIN_17                    17        ///< GPIO pin 17
#define DRV_GPIO_PIN_18                    18        ///< GPIO pin 18
#define DRV_GPIO_ALL                      (DRV_GPIO_PIN_0  | DRV_GPIO_PIN_1  | DRV_GPIO_PIN_2  | \
                                           DRV_GPIO_PIN_3  | DRV_GPIO_PIN_4  | DRV_GPIO_PIN_5  | \
                                           DRV_GPIO_PIN_6  | DRV_GPIO_PIN_7  | DRV_GPIO_PIN_8  | \
                                           DRV_GPIO_PIN_9  | DRV_GPIO_PIN_10 | DRV_GPIO_PIN_11 | \
                                           DRV_GPIO_PIN_12 | DRV_GPIO_PIN_13 | DRV_GPIO_PIN_14 | \
                                           DRV_GPIO_PIN_15 | DRV_GPIO_PIN_16 | DRV_GPIO_PIN_17 | \
                                           DRV_GPIO_PIN_18)         ///< GPIO pin all
/** @} GPIO_DRV_EC_PIN */

/**
 * @defgroup GPIO_DRV_EC_IO_SHARING GPIO IO Sharing
 * @{
 */
#define GPIO_NORMAL                        0x0          ///< gpio_instance normal
#define GPIO_DEBUG_O                       0x1          ///< gpio_instance debug function
#define GPIO0_SPI1_CLK                     0x2          ///< GPIO0 spi clk
#define GPIO1_SPI1_DATA                    0x2          ///< GPIO1 spi1 data
#define GPIO1_SPI1_MOSI                    0x3          ///< GPIO1 spi1 mosi
#define GPIO2_SPI1M_CS                     0x2          ///< GPIO2 spi1m cs
#define GPIO2_SPI1_MISO                    0x3          ///< GPIO2 spi1 miso
#define GPIO3_SPI1_CS1                     0x2          ///< GPIO3 spi1 cs1
#define GPIO4_SPI2_CLK                     0x2          ///< GPIO4 spi2 clk
#define GPIO5_SPI2_DATA                    0x2          ///< GPIO5 spi2 data
#define GPIO5_SPI2_MOSI                    0x3          ///< GPIO5 spi2 mosi
#define GPIO6_SPI2M_CS                     0x2          ///< GPIO6 spi2m cs
#define GPIO6_SPI2_MISO                    0x3          ///< GPIO6 spi2 miso
#define GPIO6_TEST_CLK_O                   0x5          ///< GPIO6 test clk
#define GPIO7_SPI2_CS1                     0x2          ///< GPIO7 spi2 cs1
#define GPIO7_UART_RX                      0x4          ///< GPIO7 uart rx
#define GPIO8_SPI2_CS3                     0x2          ///< GPIO8 spi2 cs3
#define GPIO8_SPI1_CS3                     0x3          ///< GPIO8 spi1 cs3
#define GPIO9_I2C_ADDR_CHG                 0x2          ///< GPIO9 i2c address change
#define GPIO10_I2C2S_SCK                   0x2          ///< GPIO10 i2cs sck
#define GPIO10_UART_TX                     0x3          ///< GPIO10 uart tx
#define GPIO11_I2C2S_SDA                   0x2          ///< GPIO11 i2cs sda
#define GPIO11_UART_RX                     0x3          ///< GPIO11 uart rx
#define GPIO12_EXINT2                      0x2          ///< GPIO12 exint2
#define GPIO12_XVS                         0x3          ///< GPIO12 xvs
#define GPIO13_EXT_CLK                     0x2          ///< GPIO13 ext clk
#define GPIO13_SWD                         0x3          ///< GPIO13 swd
#define GPIO14_EXINT1                      0x2          ///< GPIO14 exint 1
#define GPIO14_SWCLK                       0x3          ///< GPIO14 swclk
#define GPIO14_PWM_SYNC                    0x4          ///< GPIO14 pwm sync
#define GPIO15_UART_TX                     0x2          ///< GPIO15 uart tx
#define GPIO16_UART_RX                     0x2          ///< GPIO16 uart rx
#define GPIO17_CHIP_MODE_1                 0x1          ///< GPIO17 chip mode 1
#define GPIO18_CHIP_MODE_2                 0x1          ///< GPIO18 chip mode 2
/** @} GPIO_DRV_EC_IO_SHARING */

/**
 * @defgroup GPIO_DRV_EC_DIR GPIO direction
 * @{
 */
#define DRV_GPIO_DIR_IN                   0x0U          ///< GPIO direction input
#define DRV_GPIO_DIR_OUT                  0x1U          ///< GPIO direction output
/** @} GPIO_DRV_EC_DIR */

/**
 * @defgroup GPIO_DRV_EC_IS GPIO interrupt mode
 * @{
 */
#define DRV_GPIO_IS_EDGE                  0x0U          ///< GPIO interrupt edge detect
#define DRV_GPIO_IS_LEVEL                 0x1U          ///< GPIO interrupt level detect
/** @} GPIO_DRV_EC_IS */

/**
 * @defgroup GPIO_DRV_EC_EDGE GPIO edge decting
 * @{
 */
#define DRV_GPIO_IS_SINGLE                0x0U          ///< GPIO interrupt signle edge 
#define DRV_GPIO_IS_BOTH                  0x1U          ///< GPIO interrupt both edges
/** @} GPIO_DRV_EC_EDGE */

/**
 * @defgroup GPIO_DRV_EC_OutMode GPIO output mode
 * @{
 */
#define DRV_GPIO_OUTMODE_PUSHPULL         0x0U          ///< GPIO push pull output
#define DRV_GPIO_OUTMODE_OPENDRAIN        0x1U          ///< GPIO open drain output
/** @} GPIO_DRV_EC_OutMode */

/**
 * @defgroup GPIO_DRV_EC_Speed GPIO speed
 * @{
 */
#define DRV_GPIO_SPEED_FAST               0x0U          ///< GPIO speed fast
#define DRV_GPIO_SPEED_SLOW               0x1U          ///< GPIO speed slow
/** @} GPIO_DRV_EC_Speed */

/**
 * @defgroup GPIO_DRV_EC_PULL_DIR GPIO pull direction
 * @{
 */
#define DRV_GPIO_PULL_NO                  0x0U          ///< GPIO no pull
#define DRV_GPIO_PULL_UP                  0x1U          ///< GPIO pull up
#define DRV_GPIO_PULL_DOWN                0x2U          ///< GPIO pull down
/** @} GPIO_DRV_EC_PULL_DIR */

/** @} GPIO_DRV_Exported_Constants */

/**
 * @defgroup GPIO_DRV_Exported_Functions GPIO Drivers Exported Functions
 * @{
 */

/**
 * @defgroup GPIO_DRV_EF_Configuration GPIO Configuration Exported Functions
 * @{
 */

/**
 * @fn __STATIC_INLINE void DrvSetGpioDir(GpioTypedef* gpio_instance, uint32_t pin, uint32_t dir)
 * @brief Set GPIO direction
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @param[in] dir This parameter can be one of the following values:
              @arg @ref DRV_GPIO_DIR_IN
              @arg @ref DRV_GPIO_DIR_OUT
 */
__STATIC_INLINE void DrvSetGpioDir(GpioTypedef* gpio_instance, uint32_t pin, uint32_t dir) {
  MODIFY_REG(gpio_instance->DIR, 0x1 << pin, dir << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioDirection(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Get GPIO direction
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return GPIO direction
 * @retval DRV_GPIO_DIR_IN
 * @retval DRV_GPIO_DIR_OUT
 */
__STATIC_INLINE uint32_t DrvGetGpioDirection(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->DIR, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioData(GpioTypedef* gpio_instance, uint32_t pin, uint32_t data)
 * @brief Set Gpio data
 * 
 * @param[in] gpio_instance GPIO Instance
 * @param[in] pin Gpio pin
 * @param[in] data Gpio output data
 */
__STATIC_INLINE void DrvSetGpioData(GpioTypedef* gpio_instance, uint32_t pin, uint32_t data) {
  MODIFY_REG(gpio_instance->DATA, 0x1 << pin, data << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioData(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Set Gpio data
 * 
 * @param[in] gpio_instance GPIO Instance
 * @param[in] pin GPIO pin
 * @return GPIO input data
 */
__STATIC_INLINE uint32_t DrvGetGpioData(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->EXT, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvEnableGpioDebounce(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Enable GPIO debounce
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvEnableGpioDebounce(GpioTypedef* gpio_instance, uint32_t pin) {
  SET_BIT(gpio_instance->DB, 0x1 << pin);
}

/**
 * @fn __STATIC_INLINE void DrvDisableGpioDebounce(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Disable GPIO debounce
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvDisableGpioDebounce(GpioTypedef* gpio_instance, uint32_t pin) {
  CLEAR_BIT(gpio_instance->DB, 0x1 << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGpioDebounceIsActive(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Is GPIO debounce active
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return Debounce status
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvGpioDebounceIsActive(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->DB, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioOutMode(IOCfgTypedef *io_instance, uint32_t pin, uint32_t out_mode)
 * @brief Set GPIO output mode
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @param[in] out_mode This parameter can be one of the following values:
              @arg @ref DRV_GPIO_OUTMODE_PUSHPULL
              @arg @ref DRV_GPIO_OUTMODE_OPENDRAIN
 */
__STATIC_INLINE void DrvSetGpioOutMode(IOCfgTypedef *io_instance, uint32_t pin, uint32_t out_mode) {
  MODIFY_REG(io_instance->PIN_OD_CTRL, 0x1 << pin, out_mode << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioOutMode(IOCfgTypedef* io_instance, uint32_t pin)
 * @brief Get GPIO output mode
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @return GPIO output mode
 * @retval DRV_GPIO_OUTMODE_PUSHPULL
 * @retval DRV_GPIO_OUTMODE_OPENDRAIN
 */
__STATIC_INLINE uint32_t DrvGetGpioOutMode(IOCfgTypedef* io_instance, uint32_t pin) {
  return READ_BIT(io_instance->PIN_OD_CTRL, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioSpeed(IOCfgTypedef* io_instance, uint32_t pin, uint32_t speed)
 * @brief Set GPIO speed
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @param[in] speed This parameter can be one of the following values:
              @arg @ref DRV_GPIO_SPEED_FAST
              @arg @ref DRV_GPIO_SPEED_SLOW
 */
__STATIC_INLINE void DrvSetGpioSpeed(IOCfgTypedef* io_instance, uint32_t pin, uint32_t speed) {
  MODIFY_REG(io_instance->PIN_SL_CTRL, 0x1 << pin, speed << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioSpeed(IOCfgTypedef* io_instance, uint32_t pin)
 * @brief Get GPIO speed
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @return GPIO speed
 * @retval DRV_GPIO_SPEED_FAST
 * @retval DRV_GPIO_SPEED_SLOW
 */
__STATIC_INLINE uint32_t DrvGetGpioSpeed(IOCfgTypedef* io_instance, uint32_t pin) {
  return READ_BIT(io_instance->PIN_SL_CTRL, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioPullUpDown(IOCfgTypedef* io_instance, uint32_t pin, uint32_t pull_dir)
 * @brief Set GPIO pull up/down
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @param[in] pull_dir This parameter can be one of the following values:
              @arg @ref DRV_GPIO_PULL_NO
              @arg @ref DRV_GPIO_PULL_UP
              @arg @ref DRV_GPIO_PULL_DOWN
 */
__STATIC_INLINE void DrvSetGpioPullUpDown(IOCfgTypedef* io_instance, uint32_t pin, uint32_t pull_dir) {
  switch(pull_dir) {
    case DRV_GPIO_PULL_NO: {
      CLEAR_BIT(io_instance->PIN_PULLUP_CTRL, 0x1 << pin);
      CLEAR_BIT(io_instance->PIN_PULLDOWN_CTRL, 0x1 << pin);
      break;
    }
    case DRV_GPIO_PULL_UP: {
      MODIFY_REG(io_instance->PIN_PULLUP_CTRL, 0x1 << pin, pull_dir << pin);
      CLEAR_BIT(io_instance->PIN_PULLDOWN_CTRL, 0x1 << pin);
      break;
    }
    case DRV_GPIO_PULL_DOWN: {
      MODIFY_REG(io_instance->PIN_PULLDOWN_CTRL, 0x1 << pin, 0x01 << pin);
      CLEAR_BIT(io_instance->PIN_PULLUP_CTRL, 0x1 << pin);
      break;
    }
    default: {
      break;
    }
  }
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioPullUpDown(IOCfgTypedef* io_instance, uint32_t pin)
 * @brief Get GPIO pull direction
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @return GPIO pull direction
 * @retval DRV_GPIO_PULL_NO
 * @retval DRV_GPIO_PULL_UP
 * @retval DRV_GPIO_PULL_DOWN
 */
__STATIC_INLINE uint32_t DrvGetGpioPullUpDown(IOCfgTypedef* io_instance, uint32_t pin) {
  if((READ_BIT(io_instance->PIN_PULLUP_CTRL, 0x1 << pin) >> pin) == 0x1) {
    return DRV_GPIO_PULL_UP;
  } else if((READ_BIT(io_instance->PIN_PULLDOWN_CTRL, 0x1 << pin) >> pin) == 0x1) {
    return DRV_GPIO_PULL_DOWN;
  } else {
    return DRV_GPIO_PULL_NO;
  }
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioIOSharing(IOSharingControllerTypedef* io_instance, uint32_t pin, uint32_t function)
 * @brief Set GPIO function
 * 
 * @param[in] io_instance IO instance
 * @param[in] pin GPIO pin
 * @param[in] function GPIO function
 */
__STATIC_INLINE void DrvSetGpioIOSharing(IOSharingControllerTypedef* io_instance, uint32_t pin, uint32_t function) {
  switch(pin) {
    case DRV_GPIO_PIN_0: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SCLK1, function << PIN_FUNC_SEL0_SCLK1_Pos);
      break;
    }
    case DRV_GPIO_PIN_1: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_MOSI1, function << PIN_FUNC_SEL0_MOSI1_Pos);
      break;
    }
    case DRV_GPIO_PIN_2: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_MISO1, function << PIN_FUNC_SEL0_MISO1_Pos);
      break;
    }
    case DRV_GPIO_PIN_3: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SSB1, function << PIN_FUNC_SEL0_SSB1_Pos);
      break;
    }
    case DRV_GPIO_PIN_4: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SCLK2, function << PIN_FUNC_SEL0_SCLK2_Pos);
      break;
    }
    case DRV_GPIO_PIN_5: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_MOSI2, function << PIN_FUNC_SEL0_MOSI2_Pos);
      break;
    }
    case DRV_GPIO_PIN_6: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_MISO2, function << PIN_FUNC_SEL0_MISO2_Pos);
      break;
    }
    case DRV_GPIO_PIN_7: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SSB2, function << PIN_FUNC_SEL0_SSB2_Pos);
      break;
    }
    case DRV_GPIO_PIN_8: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SSB3, function << PIN_FUNC_SEL0_SSB3_Pos);
      break;
    }
    case DRV_GPIO_PIN_9: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_ID, function << PIN_FUNC_SEL0_ID_Pos);
      break;
    }
    case DRV_GPIO_PIN_10: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SCL2, function << PIN_FUNC_SEL0_SCL2_Pos);
      break;
    }
    case DRV_GPIO_PIN_11: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_SDA2, function << PIN_FUNC_SEL0_SDA2_Pos);
      break;
    }
    case DRV_GPIO_PIN_12: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_XVS, function << PIN_FUNC_SEL0_XVS_Pos);
      break;
    }
    case DRV_GPIO_PIN_13: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL0, PIN_FUNC_SEL0_ECLK, function << PIN_FUNC_SEL0_ECLK_Pos);
      break;
    }
    case DRV_GPIO_PIN_14: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL1, PIN_FUNC_SEL1_INT, function << PIN_FUNC_SEL1_INT_Pos);
      break;
    }
    case DRV_GPIO_PIN_15: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL1, PIN_FUNC_SEL1_GPIO0, function << PIN_FUNC_SEL1_GPIO0_Pos);
      break;
    }
    case DRV_GPIO_PIN_16: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL1, PIN_FUNC_SEL1_GPIO1, function << PIN_FUNC_SEL1_GPIO1_Pos);
      break;
    }
    case DRV_GPIO_PIN_17: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL1, PIN_FUNC_SEL1_HLXBO, function << PIN_FUNC_SEL1_HLXBO_Pos);
      break;
    }
    case DRV_GPIO_PIN_18: {
      MODIFY_REG(io_instance->PIN_FUNC_SEL1, PIN_FUNC_SEL1_HLYBO, function << PIN_FUNC_SEL1_HLYBO_Pos);
      break;
    }
    default: {
      break;
    }
  }
}

/** @} GPIO_DRV_EF_Configuration */

/**
 * @defgroup GPIO_DRV_EF_IT_Management GPIO Interrupt Management Exported Functions
 * @{
 */

/**
 * @fn __STATIC_INLINE void DrvEnableGpioIt(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Enable GPIO interrupt
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvEnableGpioIt(GpioTypedef* gpio_instance, uint32_t pin) {
  SET_BIT(gpio_instance->IEN, 0x1 << pin);
}

/**
 * @fn __STATIC_INLINE void DrvDisableGpioIt(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Disable GPIO interrupt
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvDisableGpioIt(GpioTypedef* gpio_instance, uint32_t pin) {
  CLEAR_BIT(gpio_instance->IEN, 0x1 << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGpioItIsActive(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Is GPIO interrupt active
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return interrupt status
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvGpioItIsActive(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->IEN, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioItMode(GpioTypedef* gpio_instance, uint32_t pin, uint32_t mode)
 * @brief Set GPIO interrupt mode
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @param[in] mode This parameter can be one of the following values:
              @arg @ref DRV_GPIO_IS_EDGE
              @arg @ref DRV_GPIO_IS_LEVEL
 */
__STATIC_INLINE void DrvSetGpioItMode(GpioTypedef* gpio_instance, uint32_t pin, uint32_t mode) {
  MODIFY_REG(gpio_instance->IS, 0x1 << pin, mode << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioItMode(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Get GPIO interrupt mode
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return GPIO interrupt mode
 * @retval DRV_GPIO_IS_EDGE
 * @retval DRV_GPIO_IS_LEVEL
 */
__STATIC_INLINE uint32_t DrvGetGpioItMode(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->IS, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvSetGpioEdge(GpioTypedef* gpio_instance, uint32_t pin, uint32_t edge)
 * @brief Set GPIO interrupt edge
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @param[in] edge This parameter can be one of the following values:
              @arg @ref DRV_GPIO_IS_SINGLE
              @arg @ref DRV_GPIO_IS_BOTH
 */
__STATIC_INLINE void DrvSetGpioEdge(GpioTypedef* gpio_instance, uint32_t pin, uint32_t edge) {
  MODIFY_REG(gpio_instance->IBE, 0x1 << pin, edge << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioEdge(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Get GPIO interrupt edge
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return GPIO interrupt edge
 * @retval DRV_GPIO_IS_SINGLE
 * @retval DRV_GPIO_IS_BOTH
 */
__STATIC_INLINE uint32_t DrvGetGpioEdge(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->IBE, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioItEdgeType(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Get GPIO interrupt edge type
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return GPIO interrupt edge
 * @retval DRV_GPIO_IS_SINGLE
 * @retval DRV_GPIO_IS_BOTH
 */
__STATIC_INLINE uint32_t DrvGetGpioItEdgeType(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->IEV, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioRawIt(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Is GPIO interrupt raw active
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return Interrupt raw status
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvGetGpioRawIt(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->RIS, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvEnableGpioItMask(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Enable GPIO interrupt mask
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvEnableGpioItMask(GpioTypedef* gpio_instance, uint32_t pin) {
  SET_BIT(gpio_instance->IM, 0x1 << pin);
}

/**
 * @fn __STATIC_INLINE void DrvDisableGpioItMask(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Disable GPIO interrupt mask
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvDisableGpioItMask(GpioTypedef* gpio_instance, uint32_t pin) {
  CLEAR_BIT(gpio_instance->IM, 0x1 << pin);
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGpioItMaskIsActive(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Is GPIO interrupt mask active
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return Interrupt mask active status
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvGpioItMaskIsActive(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->IM, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE uint32_t DrvGetGpioItMaskStatus(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Get GPIO interrupt mask status
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 * @return Interrupt mask status
 * @retval 1 Enable
 * @retval 0 Disable
 */
__STATIC_INLINE uint32_t DrvGetGpioItMaskStatus(GpioTypedef* gpio_instance, uint32_t pin) {
  return READ_BIT(gpio_instance->MIS, 0x1 << pin) >> pin;
}

/**
 * @fn __STATIC_INLINE void DrvClearGpioEdgeItStatus(GpioTypedef* gpio_instance, uint32_t pin)
 * @brief Clear GPIO edge interrupt status
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] pin GPIO pin
 */
__STATIC_INLINE void DrvClearGpioEdgeItStatus(GpioTypedef* gpio_instance, uint32_t pin) {
  CLEAR_BIT(gpio_instance->IC, 0x1 << pin);
}

/** @} GPIO_DRV_EF_IT_Management */

/**
 * @defgroup GPIO_DRV_EF_Init GPIO Initialization and De-initialization Exported Functions
 * @{
 */

/**
 * @fn ErrorStatus DrvGpioDeInit(GpioTypedef* gpio_instance)
 * @brief De-initialize GPIO registers
 * 
 * @param[in] gpio_instance GPIO instance
 * @return GPIO is de-initialized or not
 * @retval kSuccess GPIO registers are de-initialized
 * @retval kError GPIO registers are not de-initialized
 */
ErrorStatus DrvGpioDeInit(GpioTypedef* gpio_instance);

/**
 * @fn ErrorStatus DrvGpioInit(GpioTypedef* gpio_instance, DrvGpioInitTypedef* gpio_init_struct)
 * @brief Initialize GPIO registers according to the specified parameters in DrvGpioInitTypedef
 * 
 * @param[in] gpio_instance GPIO instance
 * @param[in] gpio_init_struct pointer to a DrvGpioInitTypedef structure that contians the 
 *            configuration information for the specified GPIO peripheral 
 * @return GPIO is initialized or not
 * @retval kSuccess GPIO registers are initialized according to gpio_init_struct content
 * @retval kError Problem occured during GPIO registers initialization
 */
ErrorStatus DrvGpioInit(GpioTypedef* TIMERx, DrvGpioInitTypedef* gpio_init_struct);

/**
 * @fn void DrvGpioStructInit(DrvGpioInitTypedef* gpio_init_struct)
 * @brief Set each @ref DrvGpioInitTypedef field to default value
 * 
 * @param[out] gpio_init_struct pointer to a @ref DrvGpioInitTypedef structure
 *             whose field will be set to default values
 */
void DrvGpioStructInit(DrvGpioInitTypedef* gpio_init_struct);

/** @} GPIO_DRV_EF_Init */
/** @} GPIO_DRV_Exported_Functions */
/** @} GPIO_DRV */
/** @} GT9881_Drivers */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* GT98XX_DRIVERS_GT98XX_DRV_GPIO_H_ */
